﻿//!CompilerOption:AddRef:System.Runtime.Remoting.dll

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using System.Threading;
using System.Windows.Media;
using Styx;
using Styx.Common;
using Styx.CommonBot;
using Styx.Helpers;
using Styx.Pathing;
using Styx.Plugins;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using ObjectManager = Styx.WoWInternals.ObjectManager;

public enum LastUsedCheck
{
    None = 0,
    VehicleCheck = 1,
    LandCheck = 2,
    MountCheck = 3,
    WorldChangeCheck = 4,
    DetectedPlayer = 5,

    TeleportedCheck = 6,
    NormalNavigationCheck = 7
};

namespace natfothPlugins
{
    public class NAssistSettings : Settings
    {
        public NAssistSettings(string settingsPath)
            : base(settingsPath)
        {
            Load();
        }

        [Setting, DefaultValue(true)]
        public bool DetectPlayers { get; set; }
        [Setting, DefaultValue(false)]
        public bool UseSpeedhack { get; set; }
        [Setting, DefaultValue(1.5)]
        public double LandSpeed { get; set; }
        [Setting, DefaultValue(2)]
        public double MountedSpeed { get; set; }
        [Setting, DefaultValue(true)]
        public bool UseTeleport { get; set; }
        [Setting, DefaultValue(false)]
        public bool UseAB { get; set; }
        [Setting, DefaultValue(500)]
        public int MinTeleportDist { get; set; }
        [Setting, DefaultValue(false)]
        public bool NoCollisionLiteMounted { get; set; }
        [Setting, DefaultValue(false)]
        public bool NoCollisionLiteAll { get; set; }
        [Setting, DefaultValue(false)]
        public bool UseClimbHack { get; set; }
        [Setting, DefaultValue(false)]
        public bool UseWaterHack { get; set; }
    }

    public class NAssist : HBPlugin
    {
        public override string Name { get { return "NAssist"; } }
        public override string Author { get { return "Natfoth"; } }
        public override Version Version { get { return new Version(1, 0, 0, 6); } }
        public override string ButtonText { get { return Name; } }
        public override bool WantButton { get { return true; } }

        internal static NAssistSettings MySettings;

        public LocalPlayer Me = StyxWoW.Me;

        //public double speedhackSpeed = 1.5;
        //public double mountedspeedhackSpeed = 1.5;
        public int TeleportDistance = 500;

        public bool StartedUp;

        public bool DetectPlayers = true;
        public bool UseTeleport = true;
        //public bool useSpeedhack = false;
        public bool UseCollisionLightMount;
        public bool UseCollisionAll;
        public bool UsingAB;
        public bool UseClimbHack;
        public bool UseWaterHack;

        public bool CollisionState;

        public LastUsedCheck LastUsed = LastUsedCheck.None;

        public static NAssist Instance { get; private set; }
        public HelperForm SettingsForm;
        public NAssist() { Instance = this; }

        private bool HasFirehack { get { return Lua.GetReturnVal<bool>("return IsFireHackLoaded", 0); } }
        private bool IsCurrentlyTeleporting { get { return Lua.GetReturnVal<bool>("return IsCurrentlyTeleporting", 0); } }

        public List<WoWPlayer> PlayerList
        {
            get
            {
                if(DetectPlayers)
                    return ObjectManager.GetObjectsOfType<WoWPlayer>()
                                            .Where(u => !u.IsDead)
                                            .OrderBy(u => u.Distance).ToList();

                return new List<WoWPlayer>();
            }
        }

       

        WoWPoint digsiteLocation;


        public override void OnButtonPress()
        {
            if (!HelperForm.IsValid)
                new HelperForm().Show();
            else
                HelperForm.Instance.Activate();
        }

        public override void Initialize()
        {
            MySettings = new NAssistSettings(Application.StartupPath + "\\Settings\\NAssist\\NAssist_Settings.xml");

            DetectPlayers = MySettings.DetectPlayers;
            UseTeleport = MySettings.UseTeleport;
            UsingAB = MySettings.UseAB;
            TeleportDistance = MySettings.MinTeleportDist;
            UseCollisionLightMount = MySettings.NoCollisionLiteMounted;
            UseCollisionAll = MySettings.NoCollisionLiteAll;
            UseClimbHack = MySettings.UseClimbHack;
            UseWaterHack = MySettings.UseWaterHack;

            Navigator.NavigationProvider = new TeleNavigator();
        }
      

        public override void Dispose()
        {
            Navigator.NavigationProvider = new MeshNavigator();
        }

        public void LogMessage(string message)
        {
            Logging.Write(Colors.Aqua, "[NAssist] " + message);
        }

        public override void Pulse()
        {
            if (Me.IsCasting)
                return;

            if (!Instance.HasFirehack)
                return;


            if (Bots.ArchaeologyBuddy.ArchBuddy.CurrentDigsite != null)
                digsiteLocation = Bots.ArchaeologyBuddy.ArchBuddy.CurrentDigsite.Location;

            string statusText = TreeRoot.StatusText.ToUpper();

            if (PlayerList.Count == 0 && LastUsed == LastUsedCheck.DetectedPlayer)
                LogMessage("Players are no longer in range!");

            Instance.LastUsed = LastUsedCheck.NormalNavigationCheck;
            
            if (UsingAB && statusText.Equals("MOVING TO THE DIGSITE", StringComparison.OrdinalIgnoreCase) && PlayerList.Count == 0)
            {
                LastUsed = LastUsedCheck.TeleportedCheck;


                if (Me.IsFalling || Me.IsSwimming || StyxWoW.Me.ZoneId <= 0 || !StyxWoW.IsInGame || StyxWoW.Me.Combat || StyxWoW.Me.IsCasting || StyxWoW.Me.IsGhost)
                        return;

                    while(Me.Mounted)
                    {
                        Mount.Dismount();
                    }

                    while(Me.IsMoving)
                    {
                        WoWMovement.MoveStop();
                    }

                    

                   /* if (UseCollisionLightMount)
                    {
                        const string m2Collision = ".event m2collision";
                        Lua.DoString("SendChatMessage(\"" + m2Collision + "\")");

                        const string wmocollision = ".event wmocollision";
                        Lua.DoString("SendChatMessage(\"" + wmocollision + "\")");
                    }

                    if(UseClimbHack)
                    {
                        const string wallclimb = ".event wallclimb";
                        Lua.DoString("SendChatMessage(\"" + wallclimb + "\")");
                    }

                    if(UseWaterHack)
                    {
                        const string waterwalk = ".event waterwalk";
                        Lua.DoString("SendChatMessage(\"" + waterwalk + "\")");
                    }*/

                    WoWPoint destToMove = digsiteLocation;

                    WoWPoint rounded; // Rounding thanks to Storm219
                    rounded.X = (float)Math.Round(destToMove.X, 2);
                    rounded.Y = (float)Math.Round(destToMove.Y, 2);
                    rounded.Z = (float)Math.Round(destToMove.Z, 2);

                    string teleport = string.Format(".go {0} {1} {2}", rounded.X, rounded.Y, rounded.Z);

                    if(HasFirehack)
                        teleport = string.Format(".port {0} {1} {2}", rounded.X, rounded.Y, rounded.Z);

                    Lua.DoString("SendChatMessage(\"" + teleport + "\")");
                    LogMessage(string.Format("Distance : {0} Location : {1}", Me.Location.Distance(rounded), teleport));

                    float safeDistance = 0;
                    int safeCount = 0;
                    if (Me.Location.Z < rounded.Z + 1 || Instance.HasFirehack)
                    {
                        while (IsCurrentlyTeleporting || rounded.Distance(Me.Location) != 0)
                        {
                            if (safeCount == 5)
                                break;


                            if (destToMove.Distance(Me.Location) == safeDistance)
                                safeCount++;

                            TreeRoot.GoalText = "Teleporting To Location";
                            TreeRoot.StatusText = "Distance: " + destToMove.Distance(StyxWoW.Me.Location);

                            Me.SetFacing(new WoWPoint(0, 0, 0));

                            Thread.Sleep(2000);

                            if (safeDistance == 0)
                                safeDistance = destToMove.Distance(Me.Location);
                        }
                    }
                    else
                    {
                        TreeRoot.GoalText = "Teleporting To Location";
                        TreeRoot.StatusText = "Distance: " + destToMove.Distance(StyxWoW.Me.Location);

                        Thread.Sleep(1000);

                        TreeRoot.GoalText = "Stopping and Falling";

                        WoWMovement.Move(WoWMovement.MovementDirection.Forward);
                        WoWMovement.MoveStop();

                        Thread.Sleep(1000);
                    }

                    TreeRoot.GoalText = "Done Teleporting";
            }

            if (PlayerList.Count > 0 && LastUsed != LastUsedCheck.DetectedPlayer && Instance.LastUsed != LastUsedCheck.NormalNavigationCheck)
            {
                LastUsed = LastUsedCheck.DetectedPlayer;

                //Disable all hacks, Players are in range!

                LogMessage("Players are within range!");

               /* if (UseCollisionLightMount)
                {
                    const string m2Collision = ".event m2collision";
                    Lua.DoString("SendChatMessage(\"" + m2Collision + "\")");

                    const string wmocollision = ".event wmocollision";
                    Lua.DoString("SendChatMessage(\"" + wmocollision + "\")");
                }

                if (UseClimbHack)
                {
                    const string wallclimb = ".event wallclimb";
                    Lua.DoString("SendChatMessage(\"" + wallclimb + "\")");
                }

                if (UseWaterHack)
                {
                    const string waterwalk = ".event waterwalk";
                    Lua.DoString("SendChatMessage(\"" + waterwalk + "\")");
                }*/
            }

            Instance.LastUsed = LastUsedCheck.NormalNavigationCheck;

        }

        public class TeleNavigator : MeshNavigator
        {
            public override MoveResult MoveTo(WoWPoint location)
            {

                LocalPlayer me = StyxWoW.Me;

                if(!Instance.HasFirehack)
                    return base.MoveTo(location);

                if (StyxWoW.Me.IsSwimming || StyxWoW.Me.ZoneId <= 0 || !StyxWoW.IsInGame || StyxWoW.Me.Combat || StyxWoW.Me.IsCasting || StyxWoW.Me.IsGhost)
                {
                    return base.MoveTo(location);
                }

                if (Instance.PlayerList.Count > 0 && Instance.LastUsed != LastUsedCheck.DetectedPlayer && Instance.LastUsed != LastUsedCheck.NormalNavigationCheck)
                {
                    Instance.LogMessage("Players are within range!");

                    Instance.LastUsed = LastUsedCheck.DetectedPlayer;
                }

                if (Instance.PlayerList.Count == 0 && Instance.LastUsed == LastUsedCheck.DetectedPlayer)
                {
                    Instance.LogMessage("Players are no longer in range!");
                }

                Instance.LastUsed = LastUsedCheck.NormalNavigationCheck;

                
                if ((location.Distance(StyxWoW.Me.Location) < Instance.TeleportDistance || Instance.PlayerList.Count > 0) || me.IsFalling || me.IsSwimming)
                {
                    return base.MoveTo(location);
                }

                while (me.Mounted)
                {
                    Mount.Dismount();
                }

                while (me.IsMoving)
                {
                    WoWMovement.MoveStop();
                }

                Instance.LastUsed = LastUsedCheck.TeleportedCheck;

                WoWPoint rounded;// Rounding thanks to Storm219
                rounded.X = (float)Math.Round(location.X, 2);
                rounded.Y = (float)Math.Round(location.Y, 2);
                rounded.Z = (float)Math.Round(location.Z, 2) +0.5f;


                string teleport = string.Format(".go {0} {1} {2}", rounded.X, rounded.Y, rounded.Z);
                if (Instance.HasFirehack)
                    teleport = string.Format(".port {0} {1} {2}", rounded.X, rounded.Y, rounded.Z);

                float safeDistance = 0;
                int safeCount = 0;

                

                Instance.LogMessage(string.Format("Distance : {0} Location : {1}", me.Location.Distance(rounded), teleport));
                Lua.DoString("SendChatMessage(\"" + teleport + "\")");


                //var isCurrentlyTeleporting = Lua.GetReturnVal<bool>("return IsCurrentlyTeleporting", 1);

                if (me.Location.Z < rounded.Z + 1 || Instance.HasFirehack)
                {
                    while (rounded.Distance(me.Location) > 1)
                    {
                        if (safeCount == 5)
                            return base.MoveTo(rounded);

                        if (location.Distance(me.Location) == safeDistance)
                            safeCount++;

                        TreeRoot.GoalText = "Teleporting To Location";
                        TreeRoot.StatusText = "Distance: " + location.Distance(StyxWoW.Me.Location);

                        Thread.Sleep(500);

                        if (safeDistance == 0)
                            safeDistance = location.Distance(me.Location);

                       // isCurrentlyTeleporting = Lua.GetReturnVal<bool>("return IsCurrentlyTeleporting", 0);


                    }

                    WoWMovement.Move(WoWMovement.MovementDirection.JumpAscend);
                    WoWMovement.MoveStop();

                    Thread.Sleep(1000);
                }
                else
                {
                    TreeRoot.GoalText = "Teleporting To Location";
                    TreeRoot.StatusText = "Distance: " + location.Distance(StyxWoW.Me.Location);

                    Thread.Sleep(1500);

                    TreeRoot.GoalText = "Stopping and Falling";

                    WoWMovement.Move(WoWMovement.MovementDirection.Forward);
                    WoWMovement.MoveStop();

                    Thread.Sleep(1000);
                }

                TreeRoot.GoalText = "Done Teleporting";
                return MoveResult.Moved;
            }
        }
    }
}